﻿using System.Diagnostics;

namespace AdvancedTimer
{
    public class Timer : IDisposable
    {
        private readonly Stopwatch Stopwatch = new();
        private CancellationTokenSource CancellationTokenSource = new();

        /// <summary>
        /// 是否自动重置
        /// </summary>
        public bool AutoReset { get; set; } = true;

        public bool IsRunning() => Stopwatch.IsRunning;
        public int? ElapsedMilliseconds { get { return Convert.ToInt32(ElapsedTicks / 10000); } set { ElapsedTicks = value * 10000; } }

        public long? ElapsedTicks { get; set; }

        /// <summary>
        /// 计时器到时事件
        /// </summary>
        public event Action? TimerElapsed;

        public Timer(int ElapsedMilliseconds)
        {
            this.ElapsedMilliseconds = ElapsedMilliseconds;
        }

        public Timer(long ElapsedTicks)
        {
            this.ElapsedTicks = ElapsedTicks;
        }
        
        /// <summary>
        /// 开启计时器
        /// </summary>
        public bool Start()
        {
            bool result = false;
            CancellationTokenSource = new();
            if (TimerElapsed != null && !CancellationTokenSource.Token.IsCancellationRequested)
            {
                Stopwatch.Start();
                long lastTick = Stopwatch.ElapsedTicks;
                Task.Factory.StartNew(() =>
                {
                    while (!CancellationTokenSource.Token.IsCancellationRequested)
                    {
                        long currentTick = Stopwatch.ElapsedTicks;
                        if (currentTick - lastTick >= ElapsedTicks)
                        {
                            if (!AutoReset) CancellationTokenSource.Cancel();
                            TimerElapsed.Invoke();
                            Debug.Print($"ThreadId：{Environment.CurrentManagedThreadId}");
                            lastTick = currentTick;
                        }
                    }
                },
                CancellationTokenSource.Token,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default);
                result = true;
            }
            return result;
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void Stop()
        {
            CancellationTokenSource?.Cancel();
            if (Stopwatch.IsRunning) Stopwatch.Stop();
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}
